%% ---------------------------------------------------------------
%% $Id: docdump.erl 24 2008-02-19 07:02:23Z kangas $
%% @author Matt Kangas <kangas@bway.net>
%% @copyright 2008 Matt Kangas. All rights reserved.
%% @end
%% ---------------------------------------------------------------
%%
%% @doc Erlang "documentation dumper"
%%
%% This code stems from a desire to have a robust, web-based (online)
%% function search engine for Erlang like http://php.net/search.php
%%
%% And... frustration from I discovering that the Erlang documentation
%% source files are not (yet) available for download
%% http://erlang.org/pipermail/erlang-questions/2008-February/032784.html
%%
%% I decided to research how tab-completion works in the Erlang shell,
%% so I could export lists of module/function names in a useful
%% open-source documentation format.
%%
%% See "edlin.erl" in lib/stdlib/src of an Erlang source distribution.
%% @end
%% ---------------------------------------------------------------

-module(docdump).
-compile(export_all).

%% @spec loaded_modules() -> [atom()]
%% @doc Returns a list of all available module names.
loaded_modules() ->
    [X || {X,_} <- code:all_loaded()].

%% @spec module_exports(Mod) -> [{atom(), Arity}]
%%      Mod = string() | atom()
%%      Arity = integer()
%% @doc Returns list of {name, arity} tuples for all functions
%% exported from a module
module_exports(Mod) when is_atom(Mod) ->
    case erlang:module_loaded(Mod) of
        true -> apply(Mod, module_info, [exports]);
        false -> no
    end;
module_exports(ModStr) when is_list(ModStr) ->
    module_exports(list_to_atom(ModStr)).

%% @spec all_modules() -> [{ModName, [Funs]}]
%%      ModName = atom()
%%      Funs = [{atom(), Arity}]
%% @doc Build list of all exported functions, in all modules
all_modules() ->
    all_modules(loaded_modules()).

all_modules([]) -> none;
all_modules([Module|T]) ->
    [{Module, module_exports(Module)} | all_modules(T)].

%% @doc Pretty-print list of all exported functions, in all modules
print_all() ->
    print_all(loaded_modules()).

print_all([]) -> none;
print_all([Mod|T]) ->
    io:format("== ~p ==~n", [Mod]),
    print_mod(Mod, module_exports(Mod)),
    print_all(T).

print_mod(_Mod, []) -> none;
print_mod(Mod, [Fun|T]) ->
    {Name,Arity} = Fun,
    io:format("  ~p:~p/~p~n", [Mod,Name,Arity]),
    print_mod(Mod,T).

